-
Notifications
You must be signed in to change notification settings - Fork 480
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Volshell: Add Dedicated Method to retrieve EPROCESS/Task object given the PID #1381
base: develop
Are you sure you want to change the base?
Conversation
Hello @the-rectifier - nice timing on this as I was recently working on a similar feature as forcing people to do the list comprehension is pretty miserable as you noted. With that said, accepting only a
To work around this, the offset (virtual or physical) needs to be allowed to be specified as this is 1) 100% precise on which process to analyze 2) supports analysis of processes found from psscan / psxview. The cleanest way in my view would be optional parameters like pid=None,v_offset=None,p_offset=None and then the code branch based on which is set. If you are willing to work these offset parameters into your code then I can drop my code as I would rather encourage more external developers to contribute to the framework. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally looks fine, thanks! Just wondering about an alias to keep the naming more consistent...
@@ -50,6 +58,7 @@ def construct_locals(self) -> List[Tuple[List[str], Any]]: | |||
result += [ | |||
(["ct", "change_task", "cp"], self.change_task), | |||
(["lt", "list_tasks", "ps"], self.list_tasks), | |||
(["gp", "get_task"], self.get_task), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do we feel about the naming? Should it be gt in linux, or will the difference be confusing? Should we call it get_process
instead to keep with windows? We can allow alternatives (see list_tasks
as both lt
and ps
in the line above). Perhaps we should have it as gt
and then with gp
as a secondary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gt
is reserved for generate_tree
afaik
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, you're right... shame... 5:S Would it be worth aliasing it to get_process
as well, or do we just live with the inconsistency?
@@ -40,6 +40,14 @@ | |||
return None | |||
print(f"No task with task ID {pid} found") | |||
|
|||
def get_task(self, pid): |
Check notice
Code scanning / CodeQL
Explicit returns mixed with implicit (fall through) returns Note
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please make sure this ends in an explicit return None
if the pid isn't found or there's no tasks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It also looks like there's two bits of whitespace that are causing black to complain
Hello @atcuno, thanks for the reply! I wasn't aware of the issues with smearing. I just hacked up a quick way to interact with structures now that I started working on my thesis. That being said, I am not that familiar with volatility internals yet, to promise a timeline. I might look into a proper version sometime in the future but I think it'd be better to continue with your codebase |
@the-rectifier don't give up yet. The basic idea would be to allow either the virtual address or physical offset to be specified and then create an _EPROCESS object at it. For physical offsets, there is a helper function:
Let me know if you have any questions. |
I'd also be wary of putting too much into the generic volshell plugin. If a plugin can do it better I think we should leave the plugin to do it (even if that includes working on a physical process offset). Linking volshell functionality against a specific plugin (even a stock one) is a bad idea, as would duplicating the functionality be. I'm sure there's a solution, but I don't think it's necessary for the immediate term... |
I would be fine with code duplication in this case, even if copy/paste from the plugin, as being limited to |
I think you mean inconvenient. I've no problem loading up specific kernel offsets physical or virtual, but making volshell depend on psscan to find them rather than having to put a couple extra lines isn't worth the complexity it would bring to the command line tool in my opinion. It's really not difficult to make use of a plugin and if that's too many lines to type, a snippet would reduce that. We're currently in a state where the dependency on simple |
The psscan link was to the I was saying that code can be copy/pasted into the volshell side to avoid the dependency. Then passing in a physical offset to get the _EPROCESS would work inside of volshell. That offset would come from the user running psscan or psxview first and noticing the hidden process. |
My bad, that function doesn't look overly complex so I think I'd be ok duplicating it too... |
Thanks for the replies, all. I played with the code a bit, and I added this to the windows side of things: kvo = self.config['kernel.offset']
ntkrnlmp = self.context.module(self.current_symbol_table, layer_name='layer_name', offset=kvo)
eproc = ntkrnlmp.object(
object_type='_EPROCESS',
offset=v_offset,
absolute=True
) As @atcuno suggested, much like the However, I still can't wrap my head around what to do when a physical address is provided. Is there a way to get from the physical address to the corresponding virtual one? |
@the-rectifier if you look at the linux.psscan as an example you'll see that the object is made with offsets on the physical layer but its native layer is set to the virtual one. It's a sort of magical 'it just works'TM magic part of vol. It allows you to make an object on one layer, but then follow any pointers etc in another. |
Also, this discussion has made me think it might be useful to share scripts that people could import by Similar to how people make use of gdb configs. I need to think about sharing all the volshell snippets I use. |
Also, we need to be slightly careful when putting in code that accessesd sub-config values using |
This PR introduces a
gp()
(get_process()/get_task()
) method to the Windows and Linux Volshell respectively.I couldn't find a way for one to (quickly) grab an arbitrary
EPROCESS
/Task
object from the shell and I thought it'd be quicker, when interactively exploring structures, to have a dedicated method rather than repeat a one-liner each time.Also, update
linux.pslist
version requirements, since they changed in fa06064: